/*
* Copyright (C) 2012
* Arindam Nath (strider2023@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.touchmenotapps.widget.radialmenu.menu.v2;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
/**
*
* @author Arindam Nath (strider2023@gmail.com)
* TODO To add in icons
*/
public class RadialMenuView extends View {
private ArrayList<RadialMenuItem> mRadialMenuContent = new ArrayList<RadialMenuItem>(0);
boolean alt;
float mWidth = -1;//center of screen, will change to touch location
float mHeight = -1;
float mThickness;
float mRadius;
int selected = -1;
int lastE = -1;//last event, used to prevent excessive redrawing
float[] endTouch;
private Paint mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Paint mSelectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private RadialMenuHelperFunctions mHelperFunctions;
/**
*
* @param context
* @param renderer
*/
public RadialMenuView(Context context, RadialMenuRenderer renderer) {
super(context);
mHelperFunctions = new RadialMenuHelperFunctions();
mRadialMenuContent = renderer.getRadialMenuContent();
alt = renderer.isAlt();
mThickness = renderer.getMenuThickness();
mRadius = renderer.getRadius();
setVisibility(GONE);
initSetPaint(renderer);
}
/**
*
* @param renderer
*/
private void initSetPaint(RadialMenuRenderer renderer) {
mBgPaint.setColor(renderer.getMenuBackgroundColor());
mBgPaint.setStrokeWidth(renderer.getMenuThickness());
mBgPaint.setStyle(Paint.Style.STROKE);
mSelectedPaint.setColor(renderer.getMenuSelectedColor());
mSelectedPaint.setStrokeWidth(renderer.getMenuThickness());
mSelectedPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setColor(renderer.getMenuBorderColor());
mBorderPaint.setStrokeWidth(renderer.getMenuThickness());
mBorderPaint.setStyle(Paint.Style.STROKE);
mTextPaint.setColor(renderer.getMenuTextColor());
mTextPaint.setTextSize((float) (renderer.getMenuThickness() / 2));
}
//prevents offscreen drawing and calcs
public void setLoc(float x, float y) {
if (x < mRadius + mThickness / 2)
x = mRadius + mThickness / 2;
if (y < mRadius + mThickness / 2)
y = mRadius + mThickness / 2;
if (y > this.getHeight() - (mRadius + mThickness / 2))
y = this.getHeight() - (mRadius + mThickness / 2);
if (x > this.getWidth() - (mRadius + mThickness / 2))
x = this.getWidth() - (mRadius + mThickness / 2);
mWidth = x;
mHeight = y;
}
@Override
public void onDraw(Canvas canvas) {
//Fixes drawing off screen
setLoc(mWidth, mHeight);
final RectF rect = new RectF();
rect.set(mWidth - mRadius, mHeight - mRadius, mWidth + mRadius, mHeight + mRadius);
int tot = mRadialMenuContent.size();
mBorderPaint.setStrokeWidth(mThickness);
//draws back of radial first
for (int counter = 0; counter < tot; counter++) {
if (!mRadialMenuContent.get(counter).equals(RadialMenuRenderer.RADIAL_NO_TEXT))
if (alt)
canvas.drawArc(rect, (float) (360 / tot * counter - 90 - 360 / tot / 2), (float) (360 / tot), false, (selected == counter ? mSelectedPaint : mBgPaint));
else
canvas.drawArc(rect, (float) (360 / tot * counter - 90), (float) (360 / tot), false, (selected == counter ? mSelectedPaint : mBgPaint));
}
//draws text
for (int counter = 0; counter < tot; counter++) {
if (!mRadialMenuContent.get(counter).equals(RadialMenuRenderer.RADIAL_NO_TEXT)) {
Path arc = new Path();
if (alt) {
arc.addArc(rect, (float) (360 / tot * counter - 90 - 360 / tot / 2) + 10, (float) (360 / tot) - 10);
canvas.drawTextOnPath(mRadialMenuContent.get(counter).getMenuName(), arc, 0, +mThickness / 8, mTextPaint);
} else {
arc.addArc(rect, (float) (360 / tot * counter - 90) + 10, (float) (360 / tot) - 10);
canvas.drawTextOnPath(mRadialMenuContent.get(counter).getMenuName(), arc, 0, -mThickness / 8, mTextPaint);
}
}
}
//draws separators between each option
if (tot > 1)
for (int counter = 0; counter < tot; counter++) {
if (!mRadialMenuContent.get(counter).equals(RadialMenuRenderer.RADIAL_NO_TEXT))
if (alt) {
canvas.drawArc(rect, (float) (360 / tot * counter - 91 - 360 / tot / 2), 2, false, mBorderPaint);
canvas.drawArc(rect, (float) (360 / tot * (counter + 1) - 91 - 360 / tot / 2), 2, false, mBorderPaint);
} else {
canvas.drawArc(rect, (float) (360 / tot * counter - 91), 2, false, mBorderPaint);
canvas.drawArc(rect, (float) (360 / tot * (counter + 1) - 91), 2, false, mBorderPaint);
}
}
//draws outer and inner boarders
mBorderPaint.setStrokeWidth(2);
rect.set(mWidth - mRadius - mThickness / 2, mHeight - mRadius - mThickness / 2, mWidth + mRadius + mThickness / 2, mHeight + mRadius + mThickness / 2);
for (int counter = 0; counter < tot; counter++) {
if (!mRadialMenuContent.get(counter).equals(RadialMenuRenderer.RADIAL_NO_TEXT))
if (alt) {
canvas.drawArc(rect, (float) (360 / tot * counter - 91 - 360 / tot / 2), (float) (360 / tot) + 2, false, mBorderPaint);
} else {
canvas.drawArc(rect, (float) (360 / tot * counter - 91), (float) (360 / tot) + 2, false, mBorderPaint);
}
}
rect.set(mWidth - mRadius + mThickness / 2, mHeight - mRadius + mThickness / 2, mWidth + mRadius - mThickness / 2, mHeight + mRadius - mThickness / 2);
for (int counter = 0; counter < tot; counter++) {
if (!mRadialMenuContent.get(counter).equals(RadialMenuRenderer.RADIAL_NO_TEXT))
if (alt) {
canvas.drawArc(rect, (float) (360 / tot * counter - 91 - 360 / tot / 2), (float) (360 / tot) + 1, false, mBorderPaint);
} else {
canvas.drawArc(rect, (float) (360 / tot * counter - 91), (float) (360 / tot) + 1, false, mBorderPaint);
}
}
}
/**
* Handles resulting event from onTouch up.
* @param e
* @return
*/
private boolean handleEvent(int e) {
if (e == mRadialMenuContent.size())
e = 0;
else if (e == -1) {
selected = -1;
return false;
}
if (mRadialMenuContent.get(e).getMenuName().equals(RadialMenuRenderer.RADIAL_NO_TEXT)) {
selected = -1;
invalidate();
return false;
}
mRadialMenuContent.get(e).getOnRadailMenuClick()
.onRadailMenuClickedListener(mRadialMenuContent.get(e).getMenuID());
selected = -1;
invalidate();
return true;
}
/**
* Handles moving gestures that haven't finished yet.
* @param e
*/
private void preEvent(int e) {
if (e == mRadialMenuContent.size())
e = 0;
else if (lastE == e)
return;
lastE = e;
if (e == -1) {
selected = -1;
invalidate();
return;
}
if (mRadialMenuContent.get(e).getMenuName().equals(RadialMenuRenderer.RADIAL_NO_TEXT)) {
selected = -1;
invalidate();
return;
}
selected = e;
invalidate();
return;
}
public boolean gestureHandler(MotionEvent event, boolean eat) {
if (event.getAction() == MotionEvent.ACTION_UP) {
endTouch = new float[] { event.getX(), event.getY() };
if (mHelperFunctions.distance(mWidth, mHeight, endTouch[0], endTouch[1]) > mRadius - mThickness / 2) {
this.setVisibility(View.GONE);
return handleEvent((int) mHelperFunctions.angle(mWidth, mHeight, endTouch[0], endTouch[1], alt, mRadialMenuContent.size()));
} else {
this.setVisibility(View.GONE);
return handleEvent(-1);
}
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
mWidth = event.getX();
mHeight = event.getY();
this.setVisibility(View.VISIBLE);
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {//drag
endTouch = new float[] { event.getX(), event.getY() };
if (mHelperFunctions.distance(mWidth, mHeight, endTouch[0], endTouch[1]) > mRadius - mThickness / 2) {
preEvent((int) mHelperFunctions.angle(mWidth, mHeight, endTouch[0], endTouch[1], alt, mRadialMenuContent.size()));
} else {
preEvent(-1);
}
}
//Eats touch if needed, fixes scrollable elements from interfering
return eat;
}
}